package entities;

import java.awt.Point;

import main.FoxMain;
import main.Map;

import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Polygon;

import shared.Camera;
import shared.MouseInput;

import items.Item;
import items.ItemBlock;
import items.Pickaxe;
import items.Sword;

public class Inventory {
	private Item[][] inventorySlots;
	private Item[] quickbar;
	private int quickbarSlots;
	private int invSlotsWidth;
	private int invSlotsHeight;
	private int activeQuickSlot;
	private boolean itemPickedUp;
	private Point inventoryPosition;
	private Point oldInventoryPosition;
	private Point newInventoryPosition;
	private int quickbarPosition;
	private int oldQuickbarPosition;
	private int newQuickbarPosition;
	
	//Draw
	private boolean inventoryActive;
	private int size;
	private int spacer;
	private int invPosX;
	private int invPosY;
	private int quickPosX;
	private int quickPosY;
	private Item selectedItem;
	
	public Inventory(int quickbarSize, int invSlotsWidth, int invSlotsHeight) throws SlickException {
		this.quickbarSlots = quickbarSize;
		this.invSlotsWidth = invSlotsWidth;
		this.invSlotsHeight = invSlotsHeight;
		
		quickbar = new Item[quickbarSize];
		inventorySlots = new Item[invSlotsWidth][invSlotsHeight];
		activeQuickSlot = 0;
		itemPickedUp = false;
		inventoryPosition = null;
		oldInventoryPosition = null;
		newInventoryPosition = null;
		quickbarPosition = -1;
		oldQuickbarPosition = -1;
		newQuickbarPosition = -1;
		
		inventoryActive = false;
		size = 40;
		spacer = 5;
		invPosX = 20;
		invPosY = 50;
		quickPosX = 20;
		quickPosY = FoxMain.getHeight() - 50;
		selectedItem = null;
		
		quickbar[0] = new Pickaxe(0, quickPosX - Camera.getShiftX() + spacer * 0 + 0 * size,
				quickPosY - Camera.getShiftY(), size, size);
		quickbar[0].setInInventory(true);
		quickbar[1] = new ItemBlock(0, quickPosX - Camera.getShiftX() + spacer * 1 + 1 * size,
				quickPosY - Camera.getShiftY(),  size, size, "stone");
		quickbar[1].setInInventory(true);
		quickbar[2] = new ItemBlock(0, quickPosX - Camera.getShiftX() + spacer * 2 + 2 * size,
				quickPosY - Camera.getShiftY(),  size, size, "earth");
		quickbar[2].setInInventory(true);
		quickbar[3] = new Sword(0, quickPosX - Camera.getShiftX() + spacer * 3 + 3 * size,
				quickPosY - Camera.getShiftY(),  size, size);
		quickbar[3].setInInventory(true);
	}
	
	public void update(GameContainer gc, int x, int y) throws SlickException {
		updateInventoryDrawStatus(gc);
		
		updateInventoryQuickbarItemPositions();
		
		updateQuickbarSelection(gc);
		
		updateInventoryQuickbarItemShiftByUser(gc, x, y);
	}
	
	private void updateQuickbarSelection(GameContainer gc) throws SlickException {
		if(gc.getInput().isKeyPressed(Input.KEY_0)) {
			setActiveQuickSlot(9);
		}
		if(gc.getInput().isKeyPressed(Input.KEY_1)) {
			setActiveQuickSlot(0);
		}
		if(gc.getInput().isKeyPressed(Input.KEY_2)) {
			setActiveQuickSlot(1);
		}
		if(gc.getInput().isKeyPressed(Input.KEY_3)) {
			setActiveQuickSlot(2);
		}
		if(gc.getInput().isKeyPressed(Input.KEY_4)) {
			setActiveQuickSlot(3);
		}
		if(gc.getInput().isKeyPressed(Input.KEY_5)) {
			setActiveQuickSlot(4);
		}
		if(gc.getInput().isKeyPressed(Input.KEY_6)) {
			setActiveQuickSlot(5);
		}
		if(gc.getInput().isKeyPressed(Input.KEY_7)) {
			setActiveQuickSlot(6);
		}
		if(gc.getInput().isKeyPressed(Input.KEY_8)) {
			setActiveQuickSlot(7);
		}
		if(gc.getInput().isKeyPressed(Input.KEY_9)) {
			setActiveQuickSlot(8);
		}
	}
	
	private void updateInventoryQuickbarItemShiftByUser(GameContainer gc, int x, int y) throws SlickException {
		if(isInventoryActive()) {
			if(gc.getInput().isMouseButtonDown(Input.MOUSE_LEFT_BUTTON)) {
				if(!isItemPickedUp()) {
					setInventoryPosition(getInventoryPositionNumberByMouse(MouseInput.getMousePosX(), MouseInput.getMousePosY()));
					setQuickbarPosition(getQuickbarPositionNumberByMouse(MouseInput.getMousePosX(), MouseInput.getMousePosY()));
					setOldInventoryPosition(getInventoryPosition());
					setOldQuickbarPosition(getQuickbarPosition());
				}
				
				//Inventarslot gefunden
				if(getInventoryPosition() != null) {
					//Slot belegt
					if(getInventoryItemByIndex((int)getInventoryPosition().getX(), (int)getInventoryPosition().getY()) != null) {
						setItemPickedUp(true);
						getInventoryItemByIndex((int)getInventoryPosition().getX(), (int)getInventoryPosition().getY()).setX(MouseInput.getMousePosX() - getSize()/2);
						getInventoryItemByIndex((int)getInventoryPosition().getX(), (int)getInventoryPosition().getY()).setY(MouseInput.getMousePosY() - getSize()/2);
						getInventoryItemByIndex((int)getInventoryPosition().getX(), (int)getInventoryPosition().getY()).setSelected(true);
					}
				}
				
				//Quickslot gefunden
				if(getQuickbarPosition() != -1) {
					//Slot belegt
					if(getQuickbarItemByIndex(getQuickbarPosition()) != null) {
						setItemPickedUp(true);
						getQuickbarItemByIndex(getQuickbarPosition()).setX(MouseInput.getMousePosX() - getSize()/2);
						getQuickbarItemByIndex(getQuickbarPosition()).setY(MouseInput.getMousePosY() - getSize()/2);
						getQuickbarItemByIndex(getQuickbarPosition()).setSelected(true);
					}
				}
			} else {
				if(isItemPickedUp()) {
					setNewInventoryPosition(getInventoryPositionNumberByMouse(MouseInput.getMousePosX(), MouseInput.getMousePosY()));
					setNewQuickbarPosition(getQuickbarPositionNumberByMouse(MouseInput.getMousePosX(), MouseInput.getMousePosY()));
				}
				
				//Inventarslot gefunden
				if(getNewInventoryPosition() != null) {
					setItemPickedUp(false);
					//Slot leer
					if(getInventoryItemByIndex((int) getNewInventoryPosition().getX(),(int) getNewInventoryPosition().getY()) == null) {
						//In Slot kopieren
						if(getOldInventoryPosition() != null) {
							setInventoryItemByIndex((int) getNewInventoryPosition().getX(),(int) getNewInventoryPosition().getY(), getInventoryItemByIndex((int) getOldInventoryPosition().getX(), (int) getOldInventoryPosition().getY()));
						} else {
							setInventoryItemByIndex((int) getNewInventoryPosition().getX(),(int) getNewInventoryPosition().getY(), getQuickbarItemByIndex(getOldQuickbarPosition()));
						}
						
						//Aus Inventar genommen
						if(getOldInventoryPosition() != null) {
							setInventoryItemByIndex((int) getOldInventoryPosition().getX(), (int) getOldInventoryPosition().getY(), null);
						}
						
						//Aus quickbar genommen
						if(getOldQuickbarPosition() != -1) {
							setQuickbarItemByIndex(getOldQuickbarPosition(), null);
						}
					} else {
						Item temp = getInventoryItemByIndex((int) getNewInventoryPosition().getX(), (int) getNewInventoryPosition().getY());
						
						//Slots tauschen
						if(getOldInventoryPosition() != null) {
							setInventoryItemByIndex((int) getNewInventoryPosition().getX(), (int) getNewInventoryPosition().getY(), getInventoryItemByIndex((int) getOldInventoryPosition().getX(), (int) getOldInventoryPosition().getY()));
							setInventoryItemByIndex((int) getOldInventoryPosition().getX(), (int) getOldInventoryPosition().getY(), temp);
						} else {
							setInventoryItemByIndex((int) getNewInventoryPosition().getX(), (int) getNewInventoryPosition().getY(), getQuickbarItemByIndex(getOldQuickbarPosition()));
							setQuickbarItemByIndex(getOldQuickbarPosition(), temp);
						}
					}
					getInventoryItemByIndex((int) getNewInventoryPosition().getX(),(int) getNewInventoryPosition().getY()).setSelected(false);
					setOldInventoryPosition(null);
					setOldQuickbarPosition(-1);
					setNewInventoryPosition(null);
					setNewQuickbarPosition(-1);
				} else if(getNewQuickbarPosition() != -1) { //Quickbar Slot gefunden
					setItemPickedUp(false);
					//Slot leer
					if(getQuickbarItemByIndex(getNewQuickbarPosition()) == null) {
						//In Slot kopieren
						if(getOldQuickbarPosition() != -1) {
							setQuickbarItemByIndex(getNewQuickbarPosition(), getQuickbarItemByIndex(getOldQuickbarPosition()));
						} else {
							setQuickbarItemByIndex(getNewQuickbarPosition(), getInventoryItemByIndex((int) getOldInventoryPosition().getX(), (int) getOldInventoryPosition().getY()));
						}
						
						//Aus Inventar genommen
						if(getOldInventoryPosition() != null) {
							setInventoryItemByIndex((int) getOldInventoryPosition().getX(), (int) getOldInventoryPosition().getY(), null);
						}
						
						//Aus quickbar genommen
						if(getOldQuickbarPosition() != -1) {
							setQuickbarItemByIndex(getOldQuickbarPosition(), null);
						}
					} else {
						Item temp = getQuickbarItemByIndex(getNewQuickbarPosition());
						
						//Slots tauschen
						if(getOldQuickbarPosition() != -1) {
							setQuickbarItemByIndex(getNewQuickbarPosition(), getQuickbarItemByIndex(getOldQuickbarPosition()));
							setQuickbarItemByIndex(getOldQuickbarPosition(), temp);
						} else {
							setQuickbarItemByIndex(getNewQuickbarPosition(), getInventoryItemByIndex((int) getOldInventoryPosition().getX(), (int) getOldInventoryPosition().getY()));
							setInventoryItemByIndex((int) getOldInventoryPosition().getX(), (int) getOldInventoryPosition().getY(), temp);
						}
					}
					getQuickbarItemByIndex(getNewQuickbarPosition()).setSelected(false);
					
					setOldInventoryPosition(null);
					setOldQuickbarPosition(-1);
					setNewInventoryPosition(null);
					setNewQuickbarPosition(-1);
				} else { //Keinen Slot gefunden - droppen
					if(getOldQuickbarPosition() != -1) {
						getQuickbarItemByIndex(getOldQuickbarPosition()).setX(x);
						getQuickbarItemByIndex(getOldQuickbarPosition()).setY(y);
						getQuickbarItemByIndex(getOldQuickbarPosition()).setInInventory(false);
						getQuickbarItemByIndex(getOldQuickbarPosition()).setJustDropped(true);
						getQuickbarItemByIndex(getOldQuickbarPosition()).setSelected(false);
						Map.addItemByIndex(Map.getItemIndexCounter(), getQuickbarItemByIndex(getOldQuickbarPosition()));
						Map.setItemIndexCounter(Map.getItemIndexCounter() + 1);
						setQuickbarItemByIndex(getOldQuickbarPosition(), null);
					} else if(getOldInventoryPosition() != null) {
						getInventoryItemByIndex((int) getOldInventoryPosition().getX(), (int) getOldInventoryPosition().getY()).setX(x);
						getInventoryItemByIndex((int) getOldInventoryPosition().getX(), (int) getOldInventoryPosition().getY()).setY(y);
						getInventoryItemByIndex((int) getOldInventoryPosition().getX(), (int) getOldInventoryPosition().getY()).setInInventory(false);
						getInventoryItemByIndex((int) getOldInventoryPosition().getX(), (int) getOldInventoryPosition().getY()).setJustDropped(true);
						getInventoryItemByIndex((int) getOldInventoryPosition().getX(), (int) getOldInventoryPosition().getY()).setSelected(false);
						Map.addItemByIndex(Map.getItemIndexCounter(), getInventoryItemByIndex((int) getOldInventoryPosition().getX(), (int) getOldInventoryPosition().getY()));
						Map.setItemIndexCounter(Map.getItemIndexCounter() + 1);
						setInventoryItemByIndex((int) getOldInventoryPosition().getX(), (int) getOldInventoryPosition().getY(), null);
					}
					
					selectedItem = null;
					setItemPickedUp(false);
					setOldInventoryPosition(null);
					setInventoryPosition(null);
					setNewInventoryPosition(null);
					setOldQuickbarPosition(-1);
					setQuickbarPosition(-1);
					setNewQuickbarPosition(-1);
				}
			}
		}
	}
	
	private Point getInventoryPositionNumberByMouse(int x, int y) {
		for(int i = 0; i < getInvSlotsWidth(); i++) {
			for(int j = 0; j < getInvSlotsHeight(); j++) {
				Polygon poly = new Polygon(new float[] {getInvPosX() - Camera.getShiftX() + getSpacer() * i + i * getSize(), getInvPosY() - Camera.getShiftY() + getSpacer() * j + j * getSize(),
														getInvPosX() - Camera.getShiftX() + getSpacer() * i + i * getSize() + getSize(), getInvPosY() - Camera.getShiftY() + getSpacer() * j + j * getSize(),
														getInvPosX() - Camera.getShiftX() + getSpacer() * i + i * getSize() + getSize(), getInvPosY() - Camera.getShiftY() + getSpacer() * j + j * getSize() + getSize(),
														getInvPosX() - Camera.getShiftX() + getSpacer() * i + i * getSize(), getInvPosY() - Camera.getShiftY() + getSpacer() * j + j * getSize() + getSize()});
				
				if(poly.contains(x, y)) {
					return new Point(i,j);
				}
				
			}
		}
		
		return null;
	}
	
	private int getQuickbarPositionNumberByMouse(int x, int y) {
		for(int i = 0; i < getQuickbarSlots(); i++) {
			Polygon poly = new Polygon(new float[] {getQuickPosX() - Camera.getShiftX() + getSpacer() * i + i * getSize(), getQuickPosY() - Camera.getShiftY(),
													getQuickPosX() - Camera.getShiftX() + getSpacer() * i + i * getSize() + getSize(), getQuickPosY() - Camera.getShiftY(),
													getQuickPosX() - Camera.getShiftX() + getSpacer() * i + i * getSize() + getSize(), getQuickPosY() - Camera.getShiftY() + getSize(),
													getQuickPosX() - Camera.getShiftX() + getSpacer() * i + i * getSize(), getQuickPosY() - Camera.getShiftY() + getSize()});
			
			if(poly.contains(x,y)) {
				return i;
			}
		}
		
		return -1;
	}
	
	private void updateInventoryQuickbarItemPositions() {
		//update quickbar item positions
		for(int i = 0; i < quickbarSlots; i++) {
			if(quickbar[i] != null) {
				//position
				quickbar[i].setX(quickPosX - Camera.getShiftX() + spacer * i + i * size);
				quickbar[i].setY(quickPosY - Camera.getShiftY());
			}
		}
		
		//update inventory item positions
		if(inventoryActive) {
			for(int i = 0; i < invSlotsWidth; i++) {
				for(int j = 0; j < invSlotsHeight; j++) {
					if(inventorySlots[i][j] != null) {
						inventorySlots[i][j].setX(invPosX - Camera.getShiftX() + spacer * i + size * i);
						inventorySlots[i][j].setY(invPosY - Camera.getShiftY() + spacer * j + size * j);
					}
				}
			}
		}
	}
	
	private void updateInventoryDrawStatus(GameContainer gc) {
		if(gc.getInput().isKeyPressed(Input.KEY_E)) {
			if(inventoryActive) {
				inventoryActive = false;
                selectedItem = null;
            } else {
				inventoryActive = true;
            }
		}
	}
	
	public void draw(Graphics g) {
		g.setColor(Color.gray);
		
		drawInventoryQuickbarSlots(g);
		
		g.setColor(Color.white);
		g.drawRect(quickPosX - Camera.getShiftX() + spacer * activeQuickSlot + activeQuickSlot * size, quickPosY - Camera.getShiftY(), size, size);
		
		drawInventoryQuickbarItems(g);
	}
	
	private void drawInventoryQuickbarSlots(Graphics g) {
		if(inventoryActive) {
			for(int i = 0; i < invSlotsWidth; i++) {
				for(int j = 0; j < invSlotsHeight; j++) {
					g.fillRect(invPosX - Camera.getShiftX() + spacer * i + i * size,
							invPosY - Camera.getShiftY() + spacer * j + j * size, size, size);
				}
			}
		}
		
		for(int i = 0; i < quickbarSlots; i++) {
			g.fillRect(quickPosX - Camera.getShiftX() + spacer * i + i * size, quickPosY - Camera.getShiftY(), size, size);
		}
	}

	private void drawInventoryQuickbarItems(Graphics g) {
		if(inventoryActive) {
			for(int i = 0; i < invSlotsWidth; i++) {
				for(int j = 0; j < invSlotsHeight; j++) {
					if(inventorySlots[i][j] != null) {
						inventorySlots[i][j].draw(g);
						
						if(inventorySlots[i][j].isSelected()) {
							selectedItem = inventorySlots[i][j];
						}
					}
				}
			}
		}
		
		for(int i = 0; i < quickbarSlots; i++) {
			if(quickbar[i] != null) {
				quickbar[i].draw(g);
				
				if(quickbar[i].isSelected()) {
					selectedItem = quickbar[i];
				}
			}
		}
		
		if(selectedItem != null)
			selectedItem.draw(g);
	}
	
	public void addItemToInventoryQuickbar(Item item) {
		//Quickbar - Item existiert
		for(int i = 0; i < quickbarSlots; i++) {
			if(quickbar[i] != null) { //Item existiert in Quickbar
				if(quickbar[i].getType().equals(item.getType())) { //Gleicher Itemtyp
					if(item.getType().equals("block")) { //Beide sind ein Block
						ItemBlock newBlock = (ItemBlock)item;
						ItemBlock oldBlock = (ItemBlock)quickbar[i];
						
						if(newBlock.getBlockType().equals(oldBlock.getBlockType())) {
							quickbar[i].setCount(quickbar[i].getCount() + 1);
							return;
						}
					}
				}
			}
		}
		
		//Inventory - Item existiert
		for(int i = 0; i < invSlotsWidth; i++) {
			for(int j = 0; j < invSlotsHeight; j++) {
				if(inventorySlots[i][j] != null) { //Item existiert
					if(inventorySlots[i][j].getType().equals(item.getType())) { //Gleicher Itemtyp
						if(item.getType().equals("block")) { //Beide Block
							ItemBlock newBlock = (ItemBlock)item;
							ItemBlock oldBlock = (ItemBlock)inventorySlots[i][j];
							
							if(newBlock.getBlockType().equals(oldBlock.getBlockType())) {
								inventorySlots[i][j].setCount(inventorySlots[i][j].getCount() + 1);
								return;
							}
						}
					}
				}
			}
		}
		
		for(int i = 0; i < quickbarSlots; i++) {
			if(quickbar[i] == null) {
				quickbar[i] = item;
				quickbar[i].setInInventory(true);
				return;
			}
		}
		
		for(int i = 0; i < invSlotsWidth; i++) {
			for(int j = 0; j < invSlotsHeight; j++) {
				if(inventorySlots[i][j] == null) {
					inventorySlots[i][j] = item;
					inventorySlots[i][j].setInInventory(true);
					return;
				}
			}
		}
	}
	
	public Item getSelectedQuickbarItem() throws SlickException {
		return quickbar[activeQuickSlot];
	}

	public int getActiveQuickSlot() {
		return activeQuickSlot;
	}

	public void setActiveQuickSlot(int activeQuickSlot) {
		this.activeQuickSlot = activeQuickSlot;
	}

	public boolean isInventoryActive() {
		return inventoryActive;
	}

	public void setInventoryActive(boolean inventoryActive) {
		this.inventoryActive = inventoryActive;
	}

	public Item getQuickbarItemByIndex(int index) {
		return quickbar[index];
	}

	public void setQuickbarItemByIndex(int index, Item item) {
		this.quickbar[index] = item;
	}
	
	public Item getInventoryItemByIndex(int i, int j) {
		return inventorySlots[i][j];
	}
	
	public void setInventoryItemByIndex(int i, int j, Item item) {
		inventorySlots[i][j] = item;
	}

	public int getQuickbarSlots() {
		return quickbarSlots;
	}

	public void setQuickbarSlots(int quickbarSlots) {
		this.quickbarSlots = quickbarSlots;
	}

	public int getInvSlotsWidth() {
		return invSlotsWidth;
	}

	public void setInvSlotsWidth(int invSlotsWidth) {
		this.invSlotsWidth = invSlotsWidth;
	}

	public int getInvSlotsHeight() {
		return invSlotsHeight;
	}

	public void setInvSlotsHeight(int invSlotsHeight) {
		this.invSlotsHeight = invSlotsHeight;
	}

	public boolean isItemPickedUp() {
		return itemPickedUp;
	}

	public void setItemPickedUp(boolean itemPickedUp) {
		this.itemPickedUp = itemPickedUp;
	}

	public Point getInventoryPosition() {
		return inventoryPosition;
	}

	public void setInventoryPosition(Point inventoryPosition) {
		this.inventoryPosition = inventoryPosition;
	}

	public Point getOldInventoryPosition() {
		return oldInventoryPosition;
	}

	public void setOldInventoryPosition(Point oldInventoryPosition) {
		this.oldInventoryPosition = oldInventoryPosition;
	}

	public Point getNewInventoryPosition() {
		return newInventoryPosition;
	}

	public void setNewInventoryPosition(Point newInventoryPosition) {
		this.newInventoryPosition = newInventoryPosition;
	}

	public int getQuickbarPosition() {
		return quickbarPosition;
	}

	public void setQuickbarPosition(int quickbarPosition) {
		this.quickbarPosition = quickbarPosition;
	}

	public int getOldQuickbarPosition() {
		return oldQuickbarPosition;
	}

	public void setOldQuickbarPosition(int oldQuickbarPosition) {
		this.oldQuickbarPosition = oldQuickbarPosition;
	}

	public int getNewQuickbarPosition() {
		return newQuickbarPosition;
	}

	public void setNewQuickbarPosition(int newQuickbarPosition) {
		this.newQuickbarPosition = newQuickbarPosition;
	}

	public int getSize() {
		return size;
	}

	public void setSize(int size) {
		this.size = size;
	}

	public int getSpacer() {
		return spacer;
	}

	public void setSpacer(int spacer) {
		this.spacer = spacer;
	}

	public int getInvPosX() {
		return invPosX;
	}

	public void setInvPosX(int invPosX) {
		this.invPosX = invPosX;
	}

	public int getInvPosY() {
		return invPosY;
	}

	public void setInvPosY(int invPosY) {
		this.invPosY = invPosY;
	}

	public int getQuickPosX() {
		return quickPosX;
	}

	public void setQuickPosX(int quickPosX) {
		this.quickPosX = quickPosX;
	}

	public int getQuickPosY() {
		return quickPosY;
	}

	public void setQuickPosY(int quickPosY) {
		this.quickPosY = quickPosY;
	}

	public Item getSelectedItem() {
		return selectedItem;
	}

	public void setSelectedItem(Item selectedItem) {
		this.selectedItem = selectedItem;
	}
}
